package Day020_NIO_AIO.demo1_Selector选择器.Test2_Selector常用方法;

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Set;

/**
 * @author zhangyan
 * @date 2020/5/13 9:38
 */
/*
    选择器常用方法:
            Selector的select()方法
                    1.此方法会阻塞，直到有至少1个客户端连接。
                    2.此方法会返回一个int值，表示有几个客户端连接了服务器
                    3.接收客户端后,不处理 不阻塞状态
                    4.处理后,又进入阻塞状态

            Selector的selectedKeys()方法
                    此方法返回一个Set集合，表示：当前已连接的通道的集合。每个已连接通道同一封装为一个SelectionKey对象
                    遍历所有被连接的服务器Channel对象的set集合
                    获取SelectionKey对象
                    调用channel方法 获得服务器channel对象

            Selector的keys()方法
                    此方法返回一个Set集合，表示：已注册通道的集合。每个已注册通道封装为一个SelectionKey对象

 */
public class Test4_Selector常用方法 {
    public static void main(String[] args) throws Exception {

        //创建3个通道，同时监听3个端口
        //获取ServerSocketChannel对象
        ServerSocketChannel channel1 = ServerSocketChannel.open();
        //设置非阻塞
        channel1.configureBlocking(false);
        //绑定端口号
        channel1.bind(new InetSocketAddress(7777));

        ServerSocketChannel channel2 = ServerSocketChannel.open();
        channel2.configureBlocking(false);
        channel2.bind(new InetSocketAddress(8888));

        ServerSocketChannel channel3 = ServerSocketChannel.open();
        channel3.configureBlocking(false);
        channel3.bind(new InetSocketAddress(9999));

        //获取选择器
        Selector selector = Selector.open();

        //把服务器通道的accept()交给选择器处理
        //注册Channel到Selector
        channel1.register(selector, SelectionKey.OP_ACCEPT);
        channel2.register(selector, SelectionKey.OP_ACCEPT);
        channel3.register(selector, SelectionKey.OP_ACCEPT);

        //1. 获取所有被连接的服务器Channel对象的set集合
        //set集合的元素类型是SelectionKey,该SelectionKey类其实是对Channel的一个封装
        Set<SelectionKey> keySet = selector.selectedKeys();
        System.out.println("被连接的服务器对象个数:" + keySet.size()); //0

        //2. 获取所有被注册的服务器Channel对象的set集合
        //set集合的元素类型是SelectionKey,该SelectionKey类其实是对Channel的一个封装
        Set<SelectionKey> keys = selector.keys();
        System.out.println("被注册的服务器对象个数:" + keys.size()); //3

        //服务器等客户端连接
        while (true) {
            System.out.println(1);
            selector.select(); // 阻塞
            System.out.println(2);

            System.out.println("被连接的服务器对象个数:" + keySet.size());

            System.out.println("被注册的服务器对象个数:" + keys.size()); //3

           /*
            //处理客户端请求代码

            //此方法返回一个Set集合，表示：当前已连接的通道的集合
            Set<SelectionKey> keySet = selector.selectedKeys();

            //遍历所有被连接的服务器Channel对象的set集合
            for (SelectionKey key : keySet) {
            //获取SelectionKey对象
                ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                SocketChannel sc = ssc.accept();
                System.out.println("开始处理....");
            }*/

        }
    }
}
